/*
 * @Author: January
 * @Date: 2022-01-04 09:49:48
 */

#include <libecc/cipher/aes.h>
#include <libecc/utils/utils.h>
#include <libecc/cipher/cipher_mode.h>


static int aes_init(aes_context* ctx, const u8* iv, int iv_len, const u8* key, int key_len, int encrypt) {
    int ret = -1;
    if (iv_len > AES_BLOCK_SIZE
    || (key_len != 16 && key_len != 24 && key_len != 32)) {
        goto out;
    }

    local_memset(ctx, 0, sizeof(*ctx));
    if (iv != NULL) {
        local_memcpy(ctx->nonce, iv, iv_len);
    }

    if (encrypt) {
        ret = AES_set_encrypt_key(key, key_len * 8, &(ctx->rk));
    } else {
        ret = AES_set_decrypt_key(key, key_len * 8, &(ctx->rk));
    }
    out:
    return ret;
}

int aes_encrypt_init(aes_context* ctx, const u8* iv, int iv_len, const u8* key, int key_len) {
    return aes_init(ctx, iv, iv_len, key, key_len, 1);
}

int aes_decrypt_init(aes_context* ctx, const u8* iv, int iv_len, const u8* key, int key_len) {
    return aes_init(ctx, iv, iv_len, key, key_len, 0);
}

void aes_encrypt_cbc(aes_context* ctx, const u8* in, int in_len, u8* out) {
    cbc_encrypt(ctx->nonce, AES_BLOCK_SIZE, &(ctx->rk), (_block_cipher)AES_encrypt, in, in_len, out);
}

void aes_decrypt_cbc(aes_context* ctx, const u8* in, int in_len, u8* out) {
    cbc_decrypt(ctx->nonce, AES_BLOCK_SIZE, &(ctx->rk), (_block_cipher)AES_decrypt, in, in_len, out);
}

void aes_process_ctr(aes_context* ctx, const u8* in, int in_len, u8* out) {
    ctr_process(ctx->nonce, AES_BLOCK_SIZE, &(ctx->rk), (_block_cipher)AES_encrypt, in, in_len, out);
}

void aes_finalize(aes_context* ctx) {
    local_memset(ctx, 0, sizeof(*ctx));
}
